home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 251_01 / advscn.c < prev    next >
Text File  |  1987-10-27  |  6KB  |  325 lines

  1. /* advscn.c - a lexical scanner for the adventure compiler */
  2. /*
  3.     Copyright (c) 1986, by David Michael Betz
  4.     All rights reserved
  5. */
  6.  
  7. #include "advcom.h"
  8.  
  9. /* useful definitions */
  10. #define maplower(ch)    (isupper(ch) ? tolower(ch) : ch)
  11.  
  12. /* global variables */
  13. int errcount=0;        /* error count */
  14. int t_value;        /* numeric value */
  15. char t_token[TKNSIZE+1];/* token string */
  16. char *t_names[] = {
  17.     0,
  18.     "(",
  19.     ")",
  20.     "STRING",
  21.     "IDENTIFIER",
  22.     "NUMBER",
  23.     "EOF"
  24. };
  25.  
  26. /* external variables */
  27. extern FILE *ifp;    /* input file pointer */
  28. extern int msgoff;    /* message section offset */
  29.  
  30. /* local variables */
  31. static int savetkn = 0;    /* look ahead token */
  32. static int savech = 0;    /* look ahead character */
  33. static char fname[200];    /* include file name */
  34. static char line[200];    /* current input line */
  35. static char *lptr;    /* line pointer */
  36. static int lnum;    /* line number */
  37. static int ieof;    /* input end of file flag */
  38. static int save_lnum;    /* saved lnum */
  39. static FILE *save_ifp;    /* saved ifp */
  40. static int scnt;    /* count of characters in string */
  41.  
  42. /* sinit - initialize the scanner */
  43. sinit()
  44. {
  45.     /* setup the line buffer */
  46.     lptr = line; *lptr = 0;
  47.     lnum = 0;
  48.  
  49.     /* no include file yet */
  50.     save_ifp = NULL;
  51.  
  52.     /* no lookahead yet */
  53.     savech = 0;
  54.     savetkn = 0;
  55.  
  56.     /* not eof yet */
  57.     ieof = FALSE;
  58. }
  59.  
  60. /* token - get the next token */
  61. int token()
  62. {
  63.     int tkn;
  64.  
  65.     if (tkn = savetkn)
  66.     savetkn = 0;
  67.     else
  68.     tkn = rtoken();
  69.     return (tkn);
  70. }
  71.  
  72. /* stoken - save a token */
  73. stoken(tkn)
  74.   int tkn;
  75. {
  76.     savetkn = tkn;
  77. }
  78.  
  79. /* rtoken - read the next token */
  80. int rtoken()
  81. {
  82.     int ch;
  83.  
  84.     /* check the next character */
  85.     for (;;)
  86.     switch (ch = skipspaces()) {
  87.     case EOF:    return (T_EOF);
  88.     case '(':    strcpy(t_token,"("); return (T_OPEN);
  89.     case ')':    strcpy(t_token,")"); return (T_CLOSE);
  90.     case '"':    return (getstring());
  91.     case ';':    while (getch() != '\n'); break;
  92.     default:    return (getid(ch));
  93.     }
  94. }
  95.  
  96. /* getstring - get a string */
  97. int getstring()
  98. {
  99.     int ch,sflag;
  100.  
  101.     t_value = msgoff;
  102.     sflag = FALSE;
  103.     scnt = 0;
  104.     while ((ch = getch()) != EOF && ch != '"')
  105.     if (isspace(ch))
  106.         sflag = TRUE;
  107.     else {
  108.         if (ch == '\\')
  109.         switch (ch = getch()) {
  110.         case 'n':  ch = '\n'; break;
  111.         case 't':  ch = '\t'; break;
  112.         }
  113.         if (sflag)
  114.         { wputc(' '); sflag = FALSE; }
  115.         wputc(ch);
  116.     }
  117.     if (sflag)
  118.     wputc(' ');
  119.     strdone();
  120.     strcpy(t_token,"{string}");
  121.     return (T_STRING);
  122. }
  123.  
  124. /* getid - get an identifier */
  125. int getid(ch)
  126.   int ch;
  127. {
  128.     char *p;
  129.  
  130.     p = t_token; *p++ = maplower(ch);
  131.     while ((ch = getch()) != EOF && isidchar(ch))
  132.     *p++ = maplower(ch);
  133.     *p = EOS;
  134.     savech = ch;
  135.     return (isnumber(t_token,&t_value) ? T_NUMBER : T_IDENTIFIER);
  136. }
  137.  
  138. /* isnumber - check if this string is a number */
  139. int isnumber(str,pval)
  140.   char *str; int *pval;
  141. {
  142.     int digits;
  143.     char *p;
  144.  
  145.     /* initialize */
  146.     p = str; digits = 0;
  147.  
  148.     /* check for a sign */
  149.     if (*p == '+' || *p == '-')
  150.     p++;
  151.  
  152.     /* check for a string of digits */
  153.     while (isdigit(*p))
  154.     p++, digits++;
  155.  
  156.     /* make sure there was at least one digit and this is the end */
  157.     if (digits == 0 || *p)
  158.     return (FALSE);
  159.  
  160.     /* convert the string to an integer and return successfully */
  161.     if (*str == '+') ++str;
  162.     *pval = atoi(str);
  163.     return (TRUE);
  164. }
  165.  
  166. /* wputc - put a character into the output file */
  167. wputc(ch)
  168.   int ch;
  169. {
  170.     ad_putc(encode(ch));
  171.     scnt++;
  172. }
  173.  
  174. /* strdone - finish a string */
  175. strdone()
  176. {
  177.     wputc('\0');
  178.     while (scnt & 3)
  179.     wputc('\0');
  180.     msgoff += scnt >> 2;
  181. }
  182.  
  183. /* skipspaces - skip leading spaces */
  184. skipspaces()
  185. {
  186.     int ch;
  187.  
  188.     while ((ch = getch()) && isspace(ch))
  189.     ;
  190.     return (ch);
  191. }
  192.  
  193. /* isidchar - is this an identifier character */
  194. int isidchar(ch)
  195.   int ch;
  196. {
  197.     return (!isspace(ch) && ch != '(' && ch != ')' && ch != '"');
  198. }
  199.  
  200. /* getch - get the next character */
  201. int getch()
  202. {
  203.     FILE *fp;
  204.     int ch;
  205.  
  206.     /* check for a lookahead character */
  207.     if (ch = savech)
  208.     savech = 0;
  209.  
  210.     /* check for a buffered character */
  211.     else if (ch = *lptr)
  212.     lptr++;
  213.  
  214.     /* check for end of file */
  215.     else if (ieof)
  216.     ch = EOF;
  217.  
  218.     /* read another line */
  219.     else {
  220.  
  221.     /* read the line */
  222.     for (lptr = line; (ch = getchr()) != EOF && (*lptr++ = ch) != '\n'; )
  223.         ;
  224.     *lptr = 0;
  225.     lnum++;
  226.  
  227.     /* check for an included file */
  228.     if (line[0] == '@') {
  229.  
  230.         /* open the file */
  231.         strcpy(fname,&line[1]); fname[strlen(fname)-1] = 0;
  232.         if ((fp = fopen(fname,"r")) == NULL) {
  233.         printf("Can't open include file: %s\n",fname);
  234.         exit();
  235.         }
  236.         printf("[ including %s ]\n",fname);
  237.  
  238.         /* setup input from the file */
  239.         save_lnum = lnum;
  240.         save_ifp = ifp;
  241.         ifp = fp;
  242.  
  243.         /* setup for the first line */
  244.         lptr = line; *lptr = 0;
  245.         lnum = 0;
  246.     }
  247.  
  248.     /* otherwise this must be an input line */
  249.     else {
  250.  
  251.         /* terminate the line with a newline */
  252.         *lptr++ = '\n'; *lptr = 0;
  253.  
  254.         /* check for end of file */
  255.         if (ch == EOF)
  256.         ieof = TRUE;
  257.  
  258.         /* update the line number and setup for the new line */
  259.         lptr = line;
  260.     }
  261.  
  262.     /* get a character */
  263.     ch = getch();
  264.     }
  265.  
  266.     /* return the current character */
  267.     return (ch);
  268. }
  269.  
  270. /* getchr - get a character checking for end of file */
  271. int getchr()
  272. {
  273.     int ch;
  274.  
  275.     if ((ch = getc(ifp)) == EOF || ch == '\032') {
  276.     if (save_ifp) {
  277.         printf("[ end of %s ]\n",fname);
  278.         fclose(ifp);
  279.         lnum = save_lnum;
  280.         ifp = save_ifp;
  281.         save_ifp = NULL;
  282.         ch = getchr();
  283.     }
  284.     else
  285.         ch = EOF;
  286.     }
  287.     else if (ch == '\r')
  288.     ch = getchr();
  289.     return (ch);
  290. }
  291.  
  292. /* encode - encode a single character */
  293. int encode(ch)
  294.   int ch;
  295. {
  296.     return ((ch - 30) & 0xFF);
  297. }
  298.  
  299. /* error - report an error in the current line */
  300. error(msg)
  301.   char *msg;
  302. {
  303.     char *p;
  304.  
  305.     printf(">>> %s <<<\n>>> in line %d <<<\n%s",msg,lnum,line);
  306.     for (p = line; p < lptr; p++)
  307.     if (*p == '\t')
  308.         putchar('\t');
  309.     else
  310.         putchar(' ');
  311.     printf("^\n");
  312.     errcount++;
  313. #ifdef MAC
  314.     macpause();
  315. #endif
  316. }
  317.  
  318. /* xerror - report an error in the current line */
  319. xerror(msg)
  320.   char *msg;
  321. {
  322.     printf(">>> %s <<<\n",msg);
  323.     errcount++;
  324. }
  325.